HJS

유틸리티 타입(Utility Types) 정리

1️⃣ 유틸리티 타입이란?

TypeScript에서 제공하는 유틸리티 타입은 기존 타입을 변형하여 새로운 타입을 쉽게 만들 수 있도록 도와주는 타입입니다.
이를 활용하면 코드를 더 간결하고 재사용 가능하게 만들 수 있습니다.

2️⃣ 주요 유틸리티 타입

🔹 Pick<T, K>

특정 속성만 선택하여 새로운 타입을 생성

interface User {
    id: number;
    name: string;
    email: string;
    password: string;
}

// ✅ 공개 가능한 사용자 정보만 포함한 타입
type PublicUser = Pick<User, "id" | "name">

const user: PublicUser = {
    id: 1,
    name: "Alice"
}

✔️ 사용처: API 응답에서 필요한 데이터만 포함할 때 활용


🔹Omit<T, K>

특정 속성을 제거하여 새로운 타입을 생성

// ✅ 비밀번호를 제외한 안전한 사용자 정보 타입
type SafeUser = Omit<User, "password">;

const safeUser: SafeUser = {
    id: 1,
    name: "Alice",
    email: "alice@example.com"
}

✔️ 사용처: 보안이 필요한 데이터를 필터링할 때 활용


💡 Omit보다는 Pick을 더 선호하는 경우가 많습니다.

✅ Pick<T, K> → 포함할 속성을 명확하게 선택할 수 있어 유지보수성과 가독성이 좋습니다 .
⚠️ Omit<T, K> → 원하지 않는 속성을 제외하지만, 나중에 타입이 확장될 경우 예기치 않은 속성이 포함될 수 있다.


🔹Readonly

모든 속성을 읽기 전용(readonly)으로 설정하는 타입

interface Config {
    apiKey: string;
    theme: string;
}

// ✅ 설정값이 변경되지 않도록 보호
const appConfig: Readonly<Config> = {
    apiKey: 123456,
    theme: "dark"
}

appConfig.apiKey = "654321" // ❌ 오류! Readonly이므로 변경 불가

✔️ 사용처: 불변 객체를 다룰 때 활용


🔹 Exclude<T, U>

T 에서 U에 해당하는 타입을 제외

type Role = "admin" | "editor" | "viewer" | "guest"

// ✅ "guest"를 제외한 권한 타입
type AuthorizedRole = Exclude<Role, "guest"> // "admin" | "editor" | "viewer"

✔️ 사용처: 특정 값만 필터링할 때 활용


🔹 Extract<T, U>

T에서 U에 할당할 수 있는 타입만 추출

// ✅ "admin"과 "editor"만 추출한 타입
type HighLevelAccess = Extract<Role, "admin" | "editor">  // "admin" | "editor"

🔹 ReturnType

함수의 반환 타입을 추출

function getProfile() {
    return { id: 1, name: "Alice", age: 25 };
}

// ✅ getProfile의 반환 타입을 가져옴
type ProfileType = ReturnType<typeof getProfile>;

// ✅ ProfileType은 { id: number; name: string; age: number } 형태

✔️ 사용처:: 함수의 반환값 타입을 재사용할 때 유용


🔹 Parameters

함수의 매개변수 타입을 튜플(tuple) 형태로 반환

function logMessage(message: string, userId: number) {
    console.log(`${userId}: ${message}`)
}

// ✅ logMessage 함수의 매개변수 타입을 추출 
type LogParams = Parameters<typeof logMessage>

// ✅ LogParams 타입은 [string, number] 형태

🔹 Awaited

promise의 결과 값을 추출

async function fetchData(): Promise<{id: number; name: string}> {
    return{ id: 1, name: "Alice" }
}

// ✅ fetchData의 반환 타입을 가져옴
type UserData = Awaited<ReturnType<typeof fetchData>>

// ✅ UserData 타입은 { id: number, name: string }

✔️ 사용처: 비동기 함수의 반환 타입을 명확히 할 때


🔹 Record<K, T>

k(key)와 T(value)를 조합하여 객체 타입을 생성

type Page = "home" | "about" | "contact"

// ✅ 각 페이지에 대한 정보를 담는 타입
const pageInfo: Record<Page, { title: string }> = {
    home: { title: "Home Page" },
    about: { title: "About Us" },
    contact: { title: "Contact Us" }
}

✔️ 사용처: 객체의 키와 값을 타입으로 제한할 때 유용




유틸리티 타입 문제

🔹 문제 1: Pick<T, K> & Omit<T, K> 활용

interface Employee {
    id: number;
    name: string;
    position: string;
    salary: number;
}

// ✅ 1-1. 직원 정보를 프론트엔드에서 표시할 때, "id"와 "name"만 포함하는 타입을 만들어라.
type EmployeePublic = ???

// ✅ 1-2. 보안상의 이유로, "salary" 정보를 제외한 타입을 만들어라.
type EmployeeSafe = ???
정답 보기 🔍
// 1-1
type EmployeePublic = Pick<Employee, "id" | "name">

// 1-2
type EmployeeSafe = Pick<Employee, "salary">

🔹 문제 2: Partial<T> & Readonly<T> 활용

interface Project {
    title: string;
    deadline: Date;
    completed: boolean;
}

// ✅ 2-1. 프로젝트 정보를 업데이트할 때, 일부만 수정할 수 있도록 타입을 정의해라.
type ProjectUpdate = ???

// ✅ 2-2. 프로젝트 정보를 불변 객체로 만들어 수정할 수 없도록 해라.
type ReadOnlyProject = ???
정답 보기 🔍
// 2-1
type ProjectUpdate = Partial<Project>

// 2-2
type ReadOnlyProject = Readonly<Project>

🔹 문제 3: Exclude<T, U> & Extract<T, U> 활용

type AccessLevel = "admin" | "editor" | "viewer" | "guest";

// ✅ 3-1. "guest" 권한을 제외한 타입을 정의해라.
type AuthorizedAccess = ???

// ✅ 3-2. "admin"과 "editor"만 포함하는 타입을 정의해라.
type HighLevelAccess = ???
정답 보기 🔍
// 3-1
type AuthorizedAccess = Exclude<AccessLevel, "guest">

// 3-2
type HighLevelAccess = Extract<AccessLevel, "admin" | "editor">

🔹 문제 4: ReturnType<T> & Parameters<T> 활용

function createOrder(productId: number, quantity: number) {
    return {
        orderId: Math.random(),
        productId,
        quantity,
        status: "pending",
    };
}

// ✅ 4-1. `createOrder` 함수의 반환 타입을 가져와라.
type OrderType = ???

// ✅ 4-2. `createOrder` 함수의 매개변수 타입을 가져와라.
type OrderParams = ???
정답 보기 🔍
// 4-1
type OrderType = ReturnType<typeof createOrder>

// 4-2
type OrderParams = Parameters<typeof createOrder>

🔹 문제 4: Awaited<T> 활용 (비동기 처리)

async function fetchUser(): Promise<{ id: number; name: string }> {
    return { id: 1, name: "Alice" };
}

// ✅ 5-1. `fetchUser`의 반환값 타입을 정의해라.
type UserType = ???
정답 보기 🔍
// 5-1
type fetchUser = Awaited<ReturnType<typeof fetchUser>>